#include <iostream>
#include "common.h"

namespace cns = chainsaw;

//
void test_print(bool test);
void test_chartool(bool test);
void test_stringtool(bool test);
void test_command(bool test);
void test_readwritefile(bool test);
void test_read_config_message(bool test);

//
void test_switch(int number);
void usage_message();
void quit_message();

int main(int argc, char **argv)
{
    cns::command cmd_tool(argc, argv);
    cmd_tool.print();

    int number = -1;
    bool loop = false;
    bool help = false;
    cmd_tool.add_option("l,loop", loop);
    cmd_tool.add_option("n,number", number);
    cmd_tool.add_option("h,help", help);
    PRP(number);
    PRP(loop);
    PRP(help);

    if(help)
    {
        usage_message();
        return 0;
    }

    if (!loop)
    {
        test_switch(number);
    }
    else
    {
        usage_message();
        quit_message();

        std::string str;
        while (std::getline(std::cin, str))
        {
            try
            {
                if (str != "q")
                {
                    number = std::stoi(str);
                    test_switch(number);
                }
                else
                {
                    return 0;
                }
            }
            catch (...)
            {
                cns::warn("invalid argument");
            }
        }
    }

    return 0;

    for (int i = 0; i < argc; ++i)
    {
        std::cout << "[" << argv[i] << "]";
    }
    std::cout << std::endl;

    PR(hi);

    test_print(false);
    test_chartool(false);
    test_stringtool(false);
    test_command(true);
    test_readwritefile(false);
    test_read_config_message(false);

    PR(ih);

    return 0;
}

#define IF_FALSE_RETURN \
    {                   \
        if (!test)      \
            return;     \
    }

void test_print(bool test)
{
    IF_FALSE_RETURN

    // OPEN_LOG_TID;
    OPEN_LOG_TIME;
    // OPEN_LOG_FILE("1.txt");
    cns::warn("print");
    PR();
    PR(1);
    PR(a);

    int a = 10;
    PRP(a = 10);
    std::vector<int> data{1, 2, 3};

    PRP(data);
    PRP2(data, the data);
    PRP("true");
    PRP('a');

    cns::info(1, 2, 3);
    cns::warn(4, 5, 6);
    cns::error(7, 8, 9);
    cns::print_class_error("main", "hi~");
}

// ok
void test_chartool(bool test)
{
    IF_FALSE_RETURN

    cns::warn("chartool");
    PRP(cns::is_upper('A'));
    PRP(cns::is_lower('A'));
    PRP(cns::to_upper('b'));
    PRP(cns::to_lower('C'));
    PRP(cns::is_alpha('1'));
    PRP(cns::is_digit('9'));
    PRP(cns::is_alnum('a'));
    PRP(cns::is_word_char('_'));
    PRP(cns::is_punct(','));
    PRP(cns::is_space('\t'));
    PRP(cns::is_hexdigit('f'));
    PRP(cns::is_print('\0'));
    PRP(cns::is_print('b'));
}

void test_stringtool(bool test)
{
    IF_FALSE_RETURN

    cns::warn("stringtool");
    std::string data = "abcdabc";

    cns::stringtool tool(data);

    PRP(tool.find('d'));
    PRP(tool.find('e'));

    PRP(tool.find("ab"));
    PRP(tool.find("ac"));

    PRP(tool.find_all('a'));

    PRP(tool.substr(1, 2));
    PRP(tool.split(3, cns::split_part::LEFT));

    std::vector<int> pos = tool.find_all('b');
    PRP(tool.split(pos));

    PRP(tool.replace(3, '3'));

    tool = cns::stringtool("hi chainsaw!");
    PRP(tool.splitWord());

    tool = cns::stringtool(" 123 ");
    PRP(tool.trimmed());

    PRP(tool.left(2));
    PRP(tool.right(2));

    PRP(tool.head());
    PRP(tool.tail());

    PRP(tool.startsWith(" "));
    PRP(tool.endsWith("3 "));
    PRP(tool.size());

    PRP(tool.remove_head());
    PRP(tool.remove_tail());
    tool.print();

    PRP(tool());
    PRP(tool[0]);

    PRP(cns::is_word(tool()));

    PRP(cns::to_upper(data));

    data = "ABC";
    PRP(cns::to_lower(data));

    std::vector<std::string> str_arr{" 123 ", " 45"};
    cns::trim(str_arr);
    PRP(str_arr);
}

void test_command(bool test)
{
    IF_FALSE_RETURN

    cns::warn("command");

    cns::command("--word xxx").print();
    cns::command("--word xx1 xx2").print();
    cns::command("--word=xxx").print();
    cns::command("--word=xx1 xx2").print();
    cns::command("-C").print();
    cns::command("-C xxx").print();
    cns::command("-C xx1 xx2").print();
    cns::command("-c").print();
    cns::command("-c xxx").print();
    cns::command("-c xx1 xx2").print();
    cns::command("-cxy").print();
    cns::command("-cxy mmm").print();
    cns::command("-cxy mm1 mm2").print();

    std::string str_cmd = "--key1 v1 --key2=v2 -A -b -cde -F v3";
    cns::command cmd_tool(str_cmd);
    cmd_tool.print();
    std::string val;
    cmd_tool.add_option("key2", val);
    PRP(val);
}

void test_readwritefile(bool test)
{
    IF_FALSE_RETURN
    auto data = cns::read_file("d:/tmp/1.txt", false);
    PRP(data);
}

void test_read_config_message(bool test)
{
    IF_FALSE_RETURN
    cns::ReadConfigMessage rcm("d:/tmp/1.txt");

    rcm.print();
}

void test_switch(int number)
{
    switch (number)
    {
    case 0:
        test_print(true);
        break;
    case 1:
        test_chartool(true);
        break;
    case 2:
        test_stringtool(true);
        break;
    case 3:
        test_command(true);
        break;
    case 4:
        test_readwritefile(true);
        break;
    case 5:
        test_read_config_message(true);
        break;
    default:
        cns::error("error number:", number);
        break;
    }
}

void usage_message()
{
    cns::info("usage:");
    cns::info("1.test_print");
    cns::info("2.test_chartool");
    cns::info("3.test_stringtool");
    cns::info("4.test_command");
    cns::info("5.test_readwritefile");
    cns::info("6.test_read_config_message");
    
}

void quit_message()
{
    cns::info("q:quit");
}
